import { showMessage } from '@/components/antd-comp/message'
import { BlockEnum, FlowNode, WorkflowType } from '@/components/workflow/types'
import { userContext } from '@/contexts/userContext'
import { getAssistantModelsApi } from '@/controllers/API/assistant'
import PluginDia from '@/pages/ApplicationEditPage/components/PluginDia'
import { generateUniqueNodeId, useWorkFlowStore } from '@/store/workflowStore'
import { MenuFoldOutlined, MenuUnfoldOutlined } from '@ant-design/icons'
import { Tooltip, message } from 'antd'
import { cloneDeep, constant } from 'lodash'
import { useCallback, useContext, useEffect, useRef, useState } from 'react'
import ReactFlow, {
  Background,
  BackgroundVariant,
  Controls,
  NodeChange,
  NodeSelectionChange,
  addEdge,
  useEdgesState,
  useNodesState
} from 'reactflow'
import BottomPanel from './bottom'
import { CUSTOM_NODE, getIterationStartNode,getIterationEndNode, getLoopStartNode, getLoopEndNode } from './constants'
import Header from './header/index'
import { useAutoSave } from './hooks/use-save'
import ExtraSidebar from './left/index'
import CustomNode from './nodes/index'
import RightPanel from './right/index'
import RunPanel from './run/panel'
import './style/index.less'
import { removeUnreachableInfo, toolDiaSaveFun, noNodeBody } from './utils'

message.config({
  duration: 2,
  maxCount: 1
})

const nodeTypes = {
  [CUSTOM_NODE]: CustomNode
}

export default function WorkflowPage({ flow }: { flow: WorkflowType }) {
  const reactFlowWrapper = useRef(null)
  const {
    flowInstance,
    selectedNode,
    flowVariables,
    errorInfo,
    setFlowInstance,
    setSelectedNode,
    addNodeInIteration,
    removeNodesInIteration,
    destroyFlow,
    setFlowVariables,
    setModelOptions,
    delFlowVariablesKey,
    coverFlowVariables,
    disabledEdit,
    updateRunType,
    deleteNode,
    clearRunInfo,
    setDisabledEdit
  } = useWorkFlowStore()

  const { autoSave } = useAutoSave()

  const { user } = useContext(userContext)

  const messageTimeout = useRef(null)
  const loadModelOptions = async () => {
    const data = await getAssistantModelsApi(user.enterprise_id)
    // 按需求，工作流中先过滤deepseek，后期打开
    //const validData = data ? data.filter(item => item.id !== 'deepseek-r1') : []
    setModelOptions(data)
  }
  // const [SelectNodeId, setSelectNodeId] = useState('')

  useEffect(() => {
    loadModelOptions()
    return () => {
      destroyFlow() // 销毁reactFlow实例
    }
  }, [])

  // 设置缩放
  useEffect(() => {
    if (flowInstance && Object.keys(flowInstance).length > 0) {
      flowInstance.setViewport(flow?.graph?.viewport || { x: 1, y: 0, zoom: 1 })
    }
  }, [flowInstance])

  const [nodes, setNodes, onNodesChange] = useNodesState(flow.graph?.nodes || [])
  const [edges, setEdges, onEdgesChange] = useEdgesState(flow.graph?.edges || [])
  
  const handleNodesChange = useCallback(
    nodes => {
      
      for (const change of nodes) {
        if (change.type === 'remove') {
          if (isDisabledEdit()) {
            return
          }
          
          if (change.id.startsWith('start') || change.id.startsWith('end') 
            || change.id.startsWith('iteration_start') 
            || change.id.startsWith('iteration_end')) {
            return
          }
          drawerClose()
          deleteNode(change.id)
        }
      }
      onNodesChange(nodes)
    },
    [onNodesChange, disabledEdit, flowInstance]
  )
  const drawerClose = () => {
    setRightPanelOpen(false)
  }

  const handleEdgesChange = useCallback(
    edges => {
      // console.log('>>>>>>edges handleEdgesChange: ', edges)
      for (const change of edges) {
        if (change.type === 'remove') {
          // 运行中或其他特殊状态禁止编辑
          if (isDisabledEdit()) {
            return
          }
        }
      }
      removeNodesInIteration(edges)
      onEdgesChange(edges)
    },
    [onEdgesChange, disabledEdit]
  )
  const onConnect = useCallback(
    params => {
      if (isDisabledEdit()) {
        return
      }
      
      // 获取开始和结束节点
      const startNode = nodes.find(node => node.id === params.source);
      const endNode = nodes.find(node => node.id === params.target);
      if (startNode.parentId !== endNode?.parentId){      
        return
      }else if(startNode?.data?.type === BlockEnum.Start && endNode?.data?.type === BlockEnum.End){
        message.warning('开始节点和结束节点不能直接连接');
        return
      }else if(startNode?.data?.type === BlockEnum.LoopStart && endNode?.data?.type === BlockEnum.LoopEnd){
        message.warning('循环开始节点和结束节点不能直接连接');
        return
      }else if(startNode?.data?.type === BlockEnum.IterationStart && endNode?.data?.type === BlockEnum.IterationEnd){
        message.warning('迭代开始节点和结束节点不能直接连接');
        return
      }


      setEdges(edges => {
        addNodeInIteration(params)
        return addEdge(params, edges)
      })
    },
    [disabledEdit, nodes]
  )

  const onDragOver = useCallback((event: React.DragEvent) => {
    // console.log('>>>>>>onDragOver', event.dataTransfer.types)
    event.preventDefault()
  }, [])

  const addCompositeNode = (type, newId, newNode) => {
    if (type === 'iteration' || type === 'loop') {
      const startNodeId = generateUniqueNodeId(`${type}_start`);
      const endNodeId = generateUniqueNodeId(`${type}_end`);
      const startNodePosition = {
        x: 50,
        y: 100
      };
      const endNodePosition = {
        x: 350,
        y: 250
      };
      
      const getNodeFunctions = {
        'iteration': {
          start: getIterationStartNode,
          end: getIterationEndNode
        },
        'loop': {
          start: getLoopStartNode,
          end: getLoopEndNode
        }
      };
  
      const startNode = getNodeFunctions[type].start(newId, startNodeId, startNodePosition);
      const endNode = getNodeFunctions[type].end(newId, endNodeId, endNodePosition);
      
      setNodes(nds => nds.concat([newNode, startNode, endNode]));
      setTimeout(() => {
        setFlowVariables(startNodeId, startNode.data.desc, {...cloneDeep(startNode.data)});
        setFlowVariables(endNodeId, endNode.data.desc, {...cloneDeep(endNode.data)});
        setFlowVariables(newId, newNode.data.title, cloneDeep(newNode.data));
      }, 0);
    } else {
      setNodes(nds => nds.concat(newNode));
      setFlowVariables(newId, newNode.data.title, cloneDeep(newNode.data));
    }
  };

  const addNodeToContainer = (containerNode, event, newNode) => {
    if (containerNode) {
      const containerId = containerNode.closest('.workflow-common-node').getAttribute('data-id');
      if (containerId) {
        newNode.parentId = containerId;
        newNode.extent = 'parent';
        
        const containerBounds = containerNode.getBoundingClientRect();
        const padding = 20;
        
        const relativeX = event.clientX - containerBounds.left;
        const relativeY = event.clientY - containerBounds.top;
        
        newNode.position = {
          x: Math.max(padding, relativeX),
          y: Math.max(padding, relativeY)
        };
      }
    }
  };

  const getNodeInfo = (target) => {
    const nodeHtml = target?.closest('.react-flow__node');
    if (!nodeHtml) return null;
    
    const node = nodes.find(n => n.id === nodeHtml.getAttribute('data-id'));
    if (!node || !node.parentId) return null;
  
    const parentNode = nodes.find(n => n.id === node.parentId);
    if (!parentNode) return null;
  
    // 构造一个新的 target 元素，指向父节点对应的 DOM 元素
    const parentNodeHtml = document.querySelector(`.react-flow__node[data-id="${parentNode.id}"]`);
    if (!parentNodeHtml) return null;
  
    // 使用父节点元素来查找容器
    const containerSelector = parentNode.data.type === 'iteration' ? '.iteration-subflow' : '.loop-subflow';
    const containerNode = parentNodeHtml.querySelector(containerSelector);
    if (!containerNode) return null;
  
    return {
      parentNode,
      containerNode
    };
  };

  const getLoopOrIterationInfo = (target) => {
    let iterationNode = target?.closest('.iteration-subflow');
    let loopNode = target?.closest('.loop-subflow');
    if(!iterationNode && !loopNode){
      // 判断target是不是迭代内的节点
      const nodeInfo = getNodeInfo(target);
      if (nodeInfo && nodeInfo.parentNode) {
        if( nodeInfo.parentNode.data.type === 'iteration'){
          iterationNode = nodeInfo.containerNode
        }else if(nodeInfo.parentNode.data.type === 'loop'){
          loopNode = nodeInfo.containerNode
        }
      }
    }

    return {
      iterationNode,
      loopNode
    };
  }

  const onDrop = useCallback(
    (event: React.DragEvent | { clientX: number; clientY: number; dataTransfer: DataTransfer } | any) => {
      event.preventDefault();
      // 运行中或其他特殊状态禁止编辑
      if (isDisabledEdit()) {
        return;
      }

      const reactFlowBounds = reactFlowWrapper.current.getBoundingClientRect();
      const dataString = event.dataTransfer.getData('nodedata');
      let data;
      try {
        data = JSON.parse(dataString);
      } catch (e) {
        console.error('Failed to parse node data:', e);
        return;
      }

      // 检查是否拖拽到迭代节点内
      const target = event.target;
      const { iterationNode, loopNode } = getLoopOrIterationInfo(target);
      const position = flowInstance.screenToFlowPosition({
        x: event.clientX - reactFlowBounds.left,
        y: event.clientY - reactFlowBounds.top
      });

      /* 判断type可点击元素 */
      if (nodeDispList(data) && !data?.model?.id && !data?.model?.name) {
        setTimeout(() => {
          setLastObj({
            lastX: event.clientX,
            lastY: event.clientY,
            iterationNode,
            loopNode
          });
          setRepeat(0);
          setFlowData(data);
          setPluginOpen(true);
        }, 100);
        return;
      }

      const { type } = data;
      const newId = generateUniqueNodeId(type);
      const newNode: FlowNode = {
        id: newId,
        type: 'flowNode',
        position,
        data: { ...data, id: newId, value: null }
      };

      // 如果拖入迭代器内，添加parentNode属性
      // if (iterationNode) {
      //   const iterationId = iterationNode.closest('.workflow-common-node').getAttribute('data-id');
      //   if (iterationId) {
      //     newNode.parentId = iterationId;
      //     newNode.extent = 'parent';
          
      //     const iterationBounds = iterationNode.getBoundingClientRect();
      //     const padding = 20;
          
      //     // 计算相对于迭代器内部的位置
      //     const relativeX = event.clientX - iterationBounds.left;
      //     const relativeY = event.clientY - iterationBounds.top;
          
      //     newNode.position = {
      //       x: Math.max(padding, relativeX),
      //       y: Math.max(padding, relativeY)
      //     };
      //   }
      // }

      // if (loopNode) {
      //   const loopId = loopNode.closest('.workflow-common-node').getAttribute('data-id');
      //   if (loopId) {
      //     newNode.parentId = loopId;
      //     newNode.extent = 'parent';
          
      //     const iterationBounds = loopNode.getBoundingClientRect();
      //     const padding = 20;
          
      //     // 计算相对于迭代器内部的位置
      //     const relativeX = event.clientX - iterationBounds.left;
      //     const relativeY = event.clientY - iterationBounds.top;
          
      //     newNode.position = {
      //       x: Math.max(padding, relativeX),
      //       y: Math.max(padding, relativeY)
      //     };
      //   }
      // }

       // 使用新的公共方法处理节点拖入容器
       addNodeToContainer(iterationNode, event, newNode);
       addNodeToContainer(loopNode, event, newNode);

      // 如果是迭代节点，自动添加起始节点
      // if (type === 'iteration') {
      //   const startNodeId = generateUniqueNodeId('iteration_start');
      //   const endNodeId = generateUniqueNodeId('iteration_end');
      //   const startNodePosition = {
      //     x: 50,
      //     y: 100
      //   };
      //   const endNodePosition = {
      //     x: 350,
      //     y: 250
      //   };
        
      //   // 先设置所有节点的 flowVariables
      //   const startNode = getIterationStartNode(newId, startNodeId, startNodePosition);
      //   const endNode = getIterationEndNode(newId, endNodeId, endNodePosition);

      //   // 然后一次性添加所有节点
      //   setNodes(nds => nds.concat([newNode, startNode, endNode]));
      //   setTimeout(() => {
      //     setFlowVariables(startNodeId, startNode.data.desc, {...cloneDeep(startNode.data)});
      //     setFlowVariables(endNodeId, endNode.data.desc, {...cloneDeep(endNode.data)});
      //     setFlowVariables(newId, data.title, cloneDeep(newNode.data));
      //   }, 0)
      // } else if (type === 'loop') {
      //     const startNodeId = generateUniqueNodeId('loop_start');
      //     const endNodeId = generateUniqueNodeId('loop_end');
      //     const startNodePosition = {
      //       x: 50,
      //       y: 100
      //     };
      //     const endNodePosition = {
      //       x: 350,
      //       y: 250
      //     };
          
      //     // 先设置所有节点的 flowVariables
      //     const startNode = getLoopStartNode(newId, startNodeId, startNodePosition);
      //     const endNode = getLoopEndNode(newId, endNodeId, endNodePosition);
  
      //     // 然后一次性添加所有节点
      //     setNodes(nds => nds.concat([newNode, startNode, endNode]));
      //     setTimeout(() => {
      //       setFlowVariables(startNodeId, startNode.data.desc, {...cloneDeep(startNode.data)});
      //       setFlowVariables(endNodeId, endNode.data.desc, {...cloneDeep(endNode.data)});
      //       setFlowVariables(newId, data.title, cloneDeep(newNode.data));
      //     }, 0)
      // } 
      // else {
      //   setNodes(nds => nds.concat(newNode));
      //   setFlowVariables(newId, data.title, cloneDeep(newNode.data));
      // }
      addCompositeNode(type, newId, newNode);
    },
    [flowInstance, setNodes, disabledEdit]
  );

  const [lastObj, setLastObj] = useState({
    lastX: 0,
    lastY: 0,
    iterationNode: null,
    loopNode: null
  })
  const [Repeat, setRepeat] = useState(0)
  /* click事件back（拖拽）回调 */
  const setNodeCallBack = data => {
    const { lastX, lastY, iterationNode, loopNode } = lastObj;
    
    // 创建模拟的数据传输对象
    const simulatedDataTransfer = {
      types: ['nodedata'],
      getData: () => data
    }
    // 构造模拟事件对象
    const simulatedEvent = {
      clientX: lastX,
      clientY: lastY,
      target: {
        closest: (selector) => {
          if (selector === '.iteration-subflow') return iterationNode;
          if (selector === '.loop-subflow') return loopNode;
          return null;
        }
      },
      dataTransfer: simulatedDataTransfer,
      preventDefault: () => {}
    }
    // 调用 onDrop 方法
    onDrop(simulatedEvent)
  }

  // 节点选中状态和右侧panel控制
  const [rightPanelOpen, setRightPanelOpen] = useState(false)
  const handleNodeClick = (event, node) => {
    // 运行中或其他特殊状态禁止编辑
    if (isDisabledEdit()) {
      return
    }
    
    // 只有迭代起始节点不允许点击
    if (noNodeBody(node.data.type)) {
      return;
    }
    
    // 点击关闭按钮时直接关闭对应窗口
    if (event.target?.dataset?.close) {
      setSelectedNode(null)
      drawerClose()
      return
    }
    // setSelectNodeId('')
    // 手动切换选中状态
    const currentSelectedNode: NodeSelectionChange = {
      id: node.id,
      type: 'select',
      selected: true
    }
    // setSelectNodeId(node.id)
    const changeNodes: NodeChange[] = [currentSelectedNode]
    const lastSelectedNode = nodes.filter(item => item.selected)
    lastSelectedNode.forEach(item => {
      if (node.id !== item.id) {
        changeNodes.push({
          id: item.id,
          type: 'select',
          selected: false
        })
      }
    })
    onNodesChange(changeNodes)

    // 移除无效溯源
    const currentFlowVariables = removeUnreachableInfo(
      node.id,
      flowInstance.getNodes(),
      flowInstance.getEdges(),
      flowVariables
    )
    coverFlowVariables(currentFlowVariables)

    // 右侧panel内容和显示控制
    setSelectedNode(node)

    setRightPanelOpen(true)
    // console.log('handleNodeClick', nodes, node, changeNodes)
  }

  useEffect(() => {
    // 检查 selectedNode 是否有效且存在于 flowVariables 中
    if (
      !selectedNode ||
      Object.keys(selectedNode).length === 0 ||
      (flowVariables && !Object.keys(flowVariables).includes(selectedNode.id))
    ) {
      drawerClose()
    }
    setRunPanelOpen(false)
  }, [selectedNode])

  const onPaneClick = nodes => {
    drawerClose()
  }
  const onRunTest = data => {
    console.log('onRunTest', data)
    drawerClose()
    setRunPanelOpen(data) // 修改为切换状态
  }

  // 运行相关
  const [runPanelOpen, setRunPanelOpen] = useState(false)

  const onRunPanelClose = (open) => {
    setRunPanelOpen(open)
    setDisabledEdit(false)
    clearRunInfo()
  }

  // 连线，位置等信息发生变更时触发一个5S后的自动保存
  useEffect(() => {
    // console.log('======nodes, edges,variables改变，触发自动保存======', nodes, edges, flowVariables)
    const timerId = setTimeout(() => {
      if (flowInstance) {
        // console.log('======nodes, edges,variables改变，触发自动保存======')
        autoSave(flow.id)
      }
    }, 1000)

    return () => {
      clearTimeout(timerId)
    }
  }, [nodes, edges, flowVariables])

  /* left显示 */
  const [leftNodeHid, setLeftNodeHid] = useState(true)
  const [showTooltip, setShowTooltip] = useState(true)

  /* bottom错误信息 */
  const [bottomPanelOpen, setBottomPanelOpen] = useState(true)

  /* 插件 */
  const [PluginOpen, setPluginOpen] = useState(false)
  const [tool_list, setTool_list] = useState([])
  const [FlowData, setFlowData] = useState({})
  const nodeDispList = data => {
    if (data.type === 'tool') {
      return true
    }
  }

  const isDisabledEdit = (showPrompt = true) => {
    if (disabledEdit) {
      if (!messageTimeout.current) {
        if (showPrompt) {
          message.warning('运行过程中请勿编辑节点')
        }
        messageTimeout.current = setTimeout(() => {
          messageTimeout.current = null
        }, 2000)
      }
      return true
    }
    return false
  }

  const onNodeDragStop = useCallback((event, node) => {
    console.log('节点移动结束:', node);
    // 如果需要，这里可以处理节点移动后的逻辑
    if (flowInstance) {
      autoSave(flow.id);
    }
  }, [flowInstance, flow.id]);

  const onNodeDrag = useCallback((event, node) => {
      if (node.parentId) {
        const parentNode = nodes.find(n => n.id === node.parentId);
        if (parentNode && (parentNode.data.type === 'iteration' || parentNode.data.type === 'loop')) {
          const newX = Math.max(20, node.position.x);
          const newY = Math.max(90, node.position.y);
          
          setNodes(nodes => 
            nodes.map(n => {
              if (n.id === node.id) {
                return {
                  ...n,
                  position: { x: newX, y: newY }
                };
              }
              return n;
            })
          );
        }
      }
    }, [nodes, setNodes]);
  
  return (
    <div className="custom-workflow-container flex h-full flex-col overflow-hidden">
      <Header flow={flow} onRunTest={onRunTest}></Header>
      <div className="flex min-h-0 flex-1 overflow-hidden">
        {leftNodeHid && <ExtraSidebar flow={flow} />}
        {/* 收起展开icon */}
        <div
          className={`cursonCase workflow-sidebar-container_icon ${
            !leftNodeHid && 'workflow-sidebar-container_icon_zero'
          }`}
          onClick={() => {
            setShowTooltip(false)
            setLeftNodeHid(!leftNodeHid)
            setTimeout(() => {
              setShowTooltip(true)
            }, 300)
          }}
        >
          {leftNodeHid && showTooltip ? (
            <Tooltip title="收起" placement="right">
              <MenuFoldOutlined />
            </Tooltip>
          ) : showTooltip ? (
            <Tooltip title="展开" placement="right">
              <MenuUnfoldOutlined />
            </Tooltip>
          ) : leftNodeHid ? (
            <MenuFoldOutlined />
          ) : (
            <MenuUnfoldOutlined />
          )}
        </div>
        <main className="flex flex-1">
          <div className="h-full w-full">
            <div className="h-full w-full" ref={reactFlowWrapper}>
              <div className="h-full w-full">
                <ReactFlow
                  nodes={nodes}
                  edges={edges}
                  nodeTypes={nodeTypes}
                  onInit={setFlowInstance}
                  onDragOver={onDragOver}
                  onDrop={onDrop}
                  onNodesChange={handleNodesChange}
                  onEdgesChange={handleEdgesChange}
                  onConnect={onConnect}
                  onNodeClick={handleNodeClick}
                  onPaneClick={onPaneClick}
                  onNodeDragStop={onNodeDragStop} 
                  onNodeDrag={onNodeDrag}
                  className="react-flow-wrapper theme-attribution"
                  minZoom={0.25}
                  maxZoom={8}
                  fitView
                  deleteKeyCode={['Delete','Backspace']}
                  edgesFocusable={true}
                  selectNodesOnDrag={false}
                  elementsSelectable={true}
                  elevateEdgesOnSelect={true}
                  proOptions={{ hideAttribution: true }} 
                  edgesUpdatable={true}
                >
                  <Background className="bg-gray-100 dark:bg-gray-950" color="#999" variant={BackgroundVariant.Dots} />
                  <Controls
                    showInteractive={false}
                    className="bg-muted fill-foreground stroke-foreground text-primary
                   [&>button]:border-b-border hover:[&>button]:bg-border"
                  ></Controls>
                </ReactFlow>
              </div>
            </div>
          </div>
        </main>
        {rightPanelOpen && selectedNode && (
          <RightPanel key={selectedNode.id} node={selectedNode} closePanel={setRightPanelOpen}></RightPanel>
        )}
        {runPanelOpen && (
          <RunPanel closePanel={onRunPanelClose} node={selectedNode} changeBottomPanelStatus={setBottomPanelOpen} />
        )}
        {bottomPanelOpen && errorInfo && (
          <BottomPanel
            left={leftNodeHid}
            right={runPanelOpen || rightPanelOpen}
            changePanelStatus={setBottomPanelOpen}
          />
        )}
        {/* 插件弹窗  */}
        {PluginOpen && (
          <PluginDia
            open={PluginOpen}
            setOpen={setPluginOpen}
            select={tool_list}
            onSelect={tool => {
              /* 显示 = id处理获取已选择 or 选择1 2 3 4 */
              // const list = [...tool_list, tool]
              // setTool_list(list)
              const list = toolDiaSaveFun(FlowData, tool)
              showMessage({
                content: `API ${tool.name} 已添加`,
                type: 'success'
              })
              //console.log(list, '====list')
              setNodeCallBack(JSON.stringify(list))
              setPluginOpen(false)
            }}
          ></PluginDia>
        )}
      </div>
    </div>
  )
}
